import numpy as np
import os
import h5py
from nilearn.connectome import ConnectivityMeasure
import matplotlib.pyplot as plt
from sklearn import manifold
from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.metrics import accuracy_score
import random

class MyClassfier():
    '''
    数据处理类
    dispose: 处理数据，返回
    myPCA: PCA降维
    addLabel: 添加类别标签
    transformDataFrame: 转换数据类型
    dataSet: 划分数据集
    '''
    def __init__(self, data_path, sort, rate, n):
        self.data_path = data_path
        self.sort = sort
        self.rate = rate
        self.n = n
        self.data, self.num = self.dispose()
        self.feature, self.corr_matrix = self.caculate()
        self.X_pca, self.y_label = self.myPCA(self.n)
        self.train_feature, self.train_label, self.test_feature, self.test_label = self.seperate()

    def dispose(self):
        '''
        return: 打乱后的数据和每一类的数量
        '''
        file_name = []
        for path in os.listdir(self.data_path):
            file_name.append(path)
        data = []
        num = [0 for i in range(len(self.sort))]
        for i in range(len(file_name)):
            f = h5py.File(self.data_path + '/' + file_name[i], 'r')
            data_timecourse = f['timecourse'][:]
            data_timecourse = data_timecourse.T
            data_label = f['label'][:][0][0]
            for i in range(len(self.sort)):
                if data_label == self.sort[i]:
                    num[i] += 1
            person = [data_timecourse, data_label]
            data.append(person)
        random.shuffle(data)
        return data, num

    def seperate(self):
        trans_data = manifold.LocallyLinearEmbedding(n_neighbors=30, n_components=2, method='standard').fit_transform(self.X_pca)
        n_train = [0 for i in range(len(self.sort))]
        n_count = [0 for i in range(len(self.sort))]
        for i in range(len(self.sort)):
            n_train[i] = self.num[i] * self.rate
        train_feature = []
        train_label = []
        test_feature = []
        test_label = []
        for i in range(len(self.y_label)):
            for j in range(len(self.sort)):
                if self.y_label[i] == self.sort[j] and n_count[j] < n_train[j]:
                    n_count[j] += 1
                    train_feature.append(trans_data[i])
                    train_label.append(self.y_label[i])
                elif self.y_label[i] == self.sort[j] and n_count[j] == n_train[j]:
                    test_feature.append(trans_data[i])
                    test_label.append(self.y_label[i])
        return train_feature, train_label, test_feature, test_label

    def caculate(self):
        correlation_measure = ConnectivityMeasure(kind='correlation')
        F = []
        for i in self.data:
            corr_matrix = correlation_measure.fit_transform([i[0]])[0]
            line = corr_matrix[np.triu_indices(corr_matrix.shape[0], k=1)]
            F.append(line)
        scaler = StandardScaler()
        feature = scaler.fit_transform(F)
        return feature, corr_matrix

    def show_coor_matrix(self):
        plt.figure(figsize=(10, 10))
        plt.imshow(self.corr_matrix)
        plt.colorbar()
        plt.title('Functional Connectivity Matrix')
        plt.show()

    def myPCA(self, n=3):
        '''
        input：
            n: 如果输入为整数，则为需要降维到几维；小数0.0-1.0为保留特征信息
        return: 降维后数据集
        '''
        pca = PCA(n_components=n)
        X_pca = np.array(pca.fit_transform(self.feature))
        y_label = np.array([x[1] for x in self.data])
        return X_pca, y_label

    def fit(self):
        model = SVC()
        model.fit(self.train_feature, self.train_label)
        predictions = model.predict(self.test_feature)
        result = accuracy_score(self.test_label, predictions)
        print("SVM分类准确率为:" + str(result))
        return result




if __name__ == "__main__":
    # 宏参数
    data_path = 'data'
    sort = [1.0, 2.0]
    rate = 0.8
    n = 10
    for i in range(3, 6):
        print("*"*12)
        print("当前降维维度为:", i)
        result = 0
        for j in range(1, n + 1):
            myclassfier = MyClassfier(data_path, sort, rate, i)
            result += myclassfier.fit()
        print(n, "次分类的平均概率为:", result/n)